package fr.inria.atlanmod.neo4emf.resourceUtil; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.emf.codegen.util.CodeGenUtil; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import org.neo4j.graphdb.DynamicRelationshipType; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.index.Index; import fr.inria.atlanmod.neo4emf.PersistentPackage; import fr.inria.atlanmod.neo4emf.Point; import fr.inria.atlanmod.neo4emf.drivers.IPersistenceService; import fr.inria.atlanmod.neo4emf.drivers.IPersistenceServiceFactory; import fr.inria.atlanmod.neo4emf.drivers.ISerializer; import fr.inria.atlanmod.neo4emf.drivers.NEConfiguration; import fr.inria.atlanmod.neo4emf.drivers.impl.NETransaction; public class Neo4emfResourceUtil { public static void importFromXMI(PersistentPackage ep, String xmiPath, String outputPath){ importFromXMI(ep, URI.createFileURI(xmiPath), outputPath); } public static void importFromXMI(PersistentPackage ep, URI xmiUri, String outputPath){ // Init variables URI uri = URI.createURI("neo4emf:///"+outputPath); NEConfiguration conf = new NEConfiguration(ep, uri, Collections.<String,String>emptyMap()); deleteFileOrDirectory(new File(outputPath)); IPersistenceService graphDB = IPersistenceServiceFactory.eINSTANCE .createPersistenceService(conf); // Serialize the resource in Neo4j DB serializeResource(graphDB, xmiUri, null); } public static void importFromXMI(PersistentPackage ep, String xmiPath, String outputPath, String ecorePath){ // Init variables URI uri = URI.createURI("neo4emf:///"+outputPath); NEConfiguration conf = new NEConfiguration(ep, uri, Collections.<String,String>emptyMap()); deleteFileOrDirectory(new File(outputPath)); IPersistenceService graphDB = IPersistenceServiceFactory.eINSTANCE .createPersistenceService(conf); // Serialize the resource in Neo4j DB Resource metaResource = initMetalmodel(ecorePath); serializeResource(graphDB,URI.createFileURI(xmiPath), metaResource); } private static Resource initMetalmodel(String ecorePath) { URI modelFileURI = URI.createURI(ecorePath); ResourceSet rSet = new ResourceSetImpl(); rSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl()); rSet.setPackageRegistry(EPackage.Registry.INSTANCE); Resource metaResource = rSet.getResource(modelFileURI, true); registerResource(metaResource); return metaResource; } public static void registerResource(Resource resource){ TreeIterator<EObject> iter = resource.getAllContents(); while (iter.hasNext()){ EObject object = iter.next(); if (object instanceof EPackage){ EPackage p = (EPackage)object; EPackage.Registry.INSTANCE.put(p.getNsURI(), p); } } } private static void serializeResource(IPersistenceService graphDB, URI xmiUri, Resource metaResource){ try { Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; Map<String, Object> map = reg.getExtensionToFactoryMap(); map.put("xmi", new XMIResourceFactoryImpl()); // Create a resource set to hold the resources. ResourceSet resourceSet = new ResourceSetImpl(); // Create a new empty resource. Resource resource = resourceSet.getResource(xmiUri, true); EList<EObject> objectsList= resourceToObjectsList(resource); Map<EObject,Long> eObjectsToNodes = persistNodes(graphDB, objectsList); persistReferences(graphDB, objectsList, eObjectsToNodes, metaResource); }finally{ graphDB.shutdown(); } } public static Map serialize (IPersistenceService graphDB, String xmiPath, Resource metaResource) { Map<EObject,Long> eObjectsToNodes = new HashMap<EObject, Long>(); try { Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; Map<String, Object> map = reg.getExtensionToFactoryMap(); map.put("xmi", new XMIResourceFactoryImpl()); // Create a resource set to hold the resources. ResourceSet resourceSet = new ResourceSetImpl(); // Create a new empty resource. URI uri = URI.createFileURI(xmiPath); Resource resource = resourceSet.getResource(uri, true); EList<EObject> objectsList= resourceToObjectsList(resource); eObjectsToNodes = persistNodes(graphDB, objectsList); persistReferences(graphDB, objectsList, eObjectsToNodes, metaResource); }finally{ graphDB.shutdown(); } return eObjectsToNodes; } public static Map<String, Map<Point, RelationshipType>>createRelationshipTypesMap(String key){ Map<String,Map<Point, RelationshipType>> result = new HashMap<String,Map<Point, RelationshipType>>(); EPackage pck = EPackage.Registry.INSTANCE.getEPackage(key); Assert.isNotNull(pck, "Unregistered ePackage with NS_URI: "+key ); Resource resource = pck.eResource(); for (EPackage ePck : getResourcePackages(resource)){ result.put(ePck.getNsURI(), createRelationshipTypesMapForPackage(ePck)); } return result; } @SuppressWarnings("unused") private static EPackage getFirstParentEPackage(EPackage pck) { return pck.getESuperPackage()== null ? pck : getFirstParentEPackage(pck.getESuperPackage()); } public static Map<Point, RelationshipType> createRelationshipTypesMapForPackage(EPackage pck){ Map<Point, RelationshipType> map = new HashMap<Point, RelationshipType>(); for (EClass clsfier : getOrderedClassifiers(pck)){ for (EStructuralFeature str : clsfier.getEAllReferences()) if (! map.containsKey(new Point(clsfier.getClassifierID(), clsfier.getFeatureID(str)))){ String stri = formatRelationshipName(clsfier,str); map.put(new Point(clsfier.getClassifierID(), str.getFeatureID()), DynamicRelationshipType.withName(stri)); } } return map; } private static Map<Point, RelationshipType> createRelTypesMap(EList<EObject> objectsList) { Map<Point, RelationshipType> map = new HashMap<Point, RelationshipType>(); for (EPackage pck : getEObjectsEPackages(objectsList)){ map.putAll(createRelationshipTypesMapForPackage(pck)); } return map; } private static Map<Point, RelationshipType> createRelTypesMap(Resource resource) { Map<Point, RelationshipType> map = new HashMap<Point, RelationshipType>(); for (EPackage pck : getResourcePackages(resource)){ map.putAll(createRelationshipTypesMapForPackage(pck)); } return map; } public static String formatRelationshipName(EClass clsfier, EStructuralFeature str) { return FormatClassifierName(clsfier) + "__" + CodeGenUtil.format(str.getName(), '_', null, false, false).toUpperCase(); } private static String FormatClassifierName(EClassifier cls) { String name = cls.getName(); String prefix = cls.getEPackage().getNsPrefix(); return CodeGenUtil.format(name, '_', prefix, true, true).toUpperCase(); } private static EList<EClass> getOrderedClassifiers(EPackage package_) { EList<EClass> result = new BasicEList<EClass>(); Set<EClass> resultSet = new HashSet<EClass>(); for (Iterator<EClass> iter = getEClasses(package_).iterator(); iter.hasNext(); ) { List<EClass> extendChain = new LinkedList<EClass>(); Set<EClass> visited = new HashSet<EClass>(); for (EClass class_ = iter.next(); class_ != null && visited.add(class_); class_ = class_.getESuperTypes().isEmpty()? null : class_.getESuperTypes().get(0)) { if (package_ == class_.getEPackage() && resultSet.add(class_)) { extendChain.add(0, class_); } } result.addAll(extendChain); } return result; } private static EList<EClass> getEClasses(EPackage package_) { EList<EClass> listCls = new BasicEList<EClass>(); for (EClassifier clsfier : package_.getEClassifiers()){ if (clsfier instanceof EClass) listCls.add((EClass)clsfier); } return listCls; } private static Set<EPackage> getEObjectsEPackages(EList<EObject> objectsList){ Set<EPackage> pckList = new HashSet<EPackage>(); Iterator<EObject> iterator = objectsList.iterator(); while (iterator.hasNext()) { EObject obj = iterator.next(); pckList.add(obj.eClass().getEPackage()); } return pckList; } private static EList<EPackage> getResourcePackages(Resource resource){ EList<EPackage> pckList = new BasicEList<EPackage>(); Iterator<EObject> iterator = resource.getAllContents(); while (iterator.hasNext()){ EObject obj = iterator.next(); if (obj instanceof EPackage) pckList.add((EPackage) obj); } return pckList; } /** * Constructor * {@code DB_PATH} the path of the data base & {@code xmiPath} path of the data base * @param DB_PATH * @param xmiPath */ public static void deleteFileOrDirectory( final File file ) { if ( !file.exists() ) return; if ( file.isDirectory() ) for ( File child : file.listFiles() ) deleteFileOrDirectory( child ); else file.delete(); } private static void persistReferences(IPersistenceService graphDB, EList<EObject> objectsList, Map<EObject,Long> eObjectsToNodes, Resource resource) { Map<Point,RelationshipType> reltypesMap; if (resource != null) { reltypesMap = createRelTypesMap(resource); } else { reltypesMap = createRelTypesMap(objectsList); } int i=0; NETransaction tx = graphDB.createTransaction(); try { for (EObject eObject : objectsList) { for (EReference eRef : eObject.eClass().getEAllReferences()) { Object value = null; try { value = eObject.eGet(eRef); } catch (ClassCastException e) {}; if (value != null) { if (eRef.isMany()){ @SuppressWarnings({"unchecked"}) EList<EObject> objList = (EList<EObject>) eObject.eGet(eRef); for (EObject eObjectEnd : objList){ createPropertyForObjects(graphDB, eObjectsToNodes, eObject, eObjectEnd, eRef, reltypesMap); } } else { EObject singleEObject = (EObject) eObject.eGet(eRef); createPropertyForObjects(graphDB, eObjectsToNodes, eObject, singleEObject, eRef, reltypesMap); } } i++; if (i==ISerializer.DEFAULT_TRANSACTIONS_COUNT){ tx.success(); tx.commit(); tx=graphDB.createTransaction(); i=0; } } } }finally{ tx.success(); tx.commit(); } } private static void createPropertyForObjects(IPersistenceService graphDB, Map<EObject, Long> eObjectsToNodes, EObject eObject, EObject eObjectEnd, EReference eRef, Map<Point,RelationshipType> reltypes) { Node node = graphDB.getNodeById(eObjectsToNodes.get(eObject)); Node nodeEnd = graphDB.getNodeById(eObjectsToNodes.get(eObjectEnd)); RelationshipType rel = DynamicRelationshipType.withName(formatRelationshipName(eObject.eClass(), eRef)); //node.createRelationshipTo(nodeEnd, reltypes.get(new Point(eObject.eClass().getClassifierID(), eRef.getFeatureID()))); node.createRelationshipTo(nodeEnd, rel); // get the reltype } private static EList<EObject> resourceToObjectsList(Resource resource){ EList<EObject> objectsList = new BasicEList<EObject>(); TreeIterator<EObject> iterator = resource.getAllContents(); while (iterator.hasNext()){ Object obj = iterator.next(); if (obj instanceof EObject) objectsList.add((EObject)obj); } return objectsList; } private static Node createWithIndexIfNotExists(EClass c, IPersistenceService graphDB ){ if (getMetaIndex(graphDB).get(IPersistenceService.ID_META, c.getEPackage().getName()+"_"+c.getClassifierID()).getSingle() != null) return getMetaIndex(graphDB).get(IPersistenceService.ID_META, c.getEPackage().getName()+"_"+c.getClassifierID()).getSingle(); Node n = graphDB.createNode(); n.setProperty(IPersistenceService.ECLASS_NAME,c.getName() ); n.setProperty(IPersistenceService.NS_URI, c.getEPackage().getNsURI()); getMetaIndex(graphDB).putIfAbsent(n, IPersistenceService.ID_META, c.getEPackage().getName()+"_"+c.getClassifierID()); return n; } public static Node createResourceNodeIfAbsent(IPersistenceService graphDB){ if (getMetaIndex(graphDB).get(IPersistenceService.ID_META, IPersistenceService.RESOURCE_NODE).getSingle() != null) return getMetaIndex(graphDB).get(IPersistenceService.ID_META, IPersistenceService.RESOURCE_NODE).getSingle(); Node n = graphDB.createNode(); getMetaIndex(graphDB).putIfAbsent(n, IPersistenceService.ID_META, IPersistenceService.RESOURCE_NODE); return n; } public static Index<Node> getMetaIndex(IPersistenceService graphDB){ return graphDB.getMetaIndex(); } public static Node createNodeFromEObject(EObject eObject,IPersistenceService graphDB) { Node node = graphDB.createNode(); Node typeNode = createWithIndexIfNotExists(eObject.eClass(), graphDB); node.createRelationshipTo(typeNode, IPersistenceService.INSTANCE_OF); if (isRoot(eObject)) createResourceNodeIfAbsent(graphDB).createRelationshipTo(node, IPersistenceService.IS_ROOT); return node; } private static boolean isRoot(EObject eObject) { if (eObject.eContainer() instanceof EPackage || eObject.eContainer() == null ) return true; return false; } private static Map<EObject, Long> persistNodes(IPersistenceService graphDB, EList<EObject> objectsList){ Map<EObject, Long> eObjectsToNodes= new HashMap<EObject,Long>(); NETransaction tx = graphDB.createTransaction(); try{ int i = 0; for (EObject eObject : objectsList){ Node n = createNodeFromEObject(eObject, graphDB); eObjectsToNodes.put(eObject, n.getId()); setupAttributes(eObject,n); i++; if (i> ISerializer.DEFAULT_TRANSACTIONS_COUNT){ i=0; tx.success(); tx.commit(); tx= graphDB.createTransaction(); } } }finally{ tx.success(); tx.commit(); } return eObjectsToNodes; } @SuppressWarnings("unchecked") private static void setupAttributes(EObject eObject, Node n) { // TODO Auto-generated method stub EList<EAttribute> atrList= eObject.eClass().getEAllAttributes(); java.util.Iterator<EAttribute> it = atrList.iterator(); while(it.hasNext()){ EAttribute at =it.next(); if (eObject.eGet(at)!= null && !at.isMany()){ if (at.getEType() instanceof EEnum) n.setProperty(at.getName(), eObject.eGet(at).toString()); else if (isPrimitive(at.getName())) n.setProperty(at.getName(), eObject.eGet(at)); else n.setProperty(at.getName(), eObject.eGet(at).toString()); } else if (eObject.eGet(at) != null && at.isMany()){ n.setProperty(at.getName(), ((EList<EDataType>) eObject.eGet(at)).toArray());} else if (!at.isMany()){ if (at.getEType().getInstanceClass().isAssignableFrom(Boolean.class)) n.setProperty(at.getName(), false ); else if (at.getEType().getInstanceClass().isAssignableFrom(String.class)) n.setProperty(at.getName(), ""); else if (at.getEType().getInstanceClass().isAssignableFrom(Integer.class)) n.setProperty(at.getName(), 0); else n.setProperty(at.getName(), 0); } else {n.setProperty(at.getName(), new Object[1]);} } } private static boolean isPrimitive(String str){ if (str.equals("Boolean") || str.equals("Integer") || str.equals("Short") || str.equals("Long") || str.equals("Float") || str.equals("String") || str.equals("Double")) return false; return true; } @SuppressWarnings("unused") private static String formatUniquePackageName(EPackage pck){ return formatUniquePackageNameLevel_i(pck,"",0); } private static String formatUniquePackageNameLevel_i(EPackage pck, String string, int i) { String underScores = ""; for (int j=0;j>i;j++) underScores+="_"; String localName= underScores+pck.getNsURI(); string +=localName; return pck.getESuperPackage()!=null ? formatUniquePackageNameLevel_i(pck,string,i+1): string; } public static URI createNeo4emfURI(File file) { URI fileUri = URI.createFileURI(file.getAbsolutePath()); URI uri = URI.createHierarchicalURI( "neo4emf", fileUri.authority(), fileUri.device(), fileUri.segments(), fileUri.query(), fileUri.fragment()); return uri; } }